#include <memory>
#include <iostream>
#include <functional>
// 增加T类型
struct T
{
    int a;
};

int main()
{
    // 创建一个 unique_ptr 并初始化
    std::unique_ptr<T> myPtr = std::make_unique<T>();

    // 尝试复制 unique_ptr（这将导致编译错误）
    // std::unique_ptr<T> myOtherPtr = myPtr; // 错误，不能复制

    // 正确地通过移动语义转移所有权
    std::unique_ptr<T> myOtherPtr = std::move(myPtr);

    // 再次尝试使用已经转移所有权的 myPtr（这将导致编译错误）
    // std::unique_ptr<T> ptr = myPtr; // 错误，只能移动，不能复制

    // 在unique_ptr中确定删除器
    // 删除器是一个函数指针 注意 不能捕获 捕获应该用function

    std::unique_ptr<T, void (*)(T *)> p3(new T, [](T *p)
                                         { std::cout << "delete int" << std::endl; delete p; });

    // 使用std::function的捕获
    std::unique_ptr<T, std::function<void(T *)>> p4(new T, [](T *p)
                                                    { std::cout << "delete int by functon" << std::endl; delete p; });
    //
    int p1 = 20;
    std::unique_ptr<T, std::function<void(T *)>> p5(new T, [&p1](T *p)
                                                    { std::cout << "delete int by functon" << std::endl;
                                                    //修改p1的值
                                                    p1 = 30;
                                                     delete p;
                                                     //打印p1
                                                    std::cout << "p1: " << p1 << std::endl; });
    // 打印p1
    std::cout << "p1: " << p1 << std::endl;
    // 自定义一个仿函数
    // 使用仿函数就只需要在模板类将删除器类型指定为仿函数类型
    // 不需要在函数构造中调用了
    struct MyDeleter
    {
        void operator()(T *p)
        {
            std::cout << "delete int by function p6" << std::endl;
            delete p;
        }
    };
    std::unique_ptr<T, MyDeleter> p6(new T);
    return 0;
}